package com.to8to.scene.stat;

import static com.to8to.scene.server.Commons.mongo;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mongodb.BasicDBObject;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.QueryOperators;
import com.to8to.commons.utils.StringUtil;
import com.to8to.commons.utils.ThriftUtil;
import com.to8to.scene.server.Commons;
import com.to8to.scene.server.Tables;
import com.to8to.thrift.diary.consts.constConstants;
import com.to8to.thrift.diary.module.TComment;
import com.to8to.thrift.diary.module.TDiary;
import com.to8to.thrift.diary.module.TDiaryStat;
import com.to8to.thrift.diary.module.TProduct;

/**
 * 与StatSceneUpdateEngine中的代码有重复，但是保持了灵活性
 * @author alpha.ren
 *
 */
public class StatDiaryUpdateEngine extends AbstractStatUpdate
{
    public static Logger logger = LoggerFactory.getLogger(StatDiaryUpdateEngine.class);

    @Override
    public void asyncUpdate(String diary_id)
    {
        BasicDBObject update_db = new BasicDBObject();

        BasicDBObject diary_db = (BasicDBObject) Commons.mongo.findById(Tables.Diary, diary_id);
        TDiary diary = null;
        if (null != diary_db)
            diary = ThriftUtil.dbObject2ThriftObject(diary_db, TDiary.class);
        if (diary == null)
            return;

        int recent_time = diary.getUtime();
        int recent_event = constConstants.RECENT_EVENT_DIARY;
        String recent_user = diary.getOwner_id();

        /* IMAGE_NUM */
        int image_num = 0;
        if (null != diary.getImages())
            image_num = diary.getImagesSize();

        /* COMMENT */
        List<TComment> comment_list = new ArrayList();

        DBCursor comment_cursor =
            Commons.mongo.cursor(Tables.Comment, new BasicDBObject(TComment._Fields.DIARY_ID.getFieldName(), diary_id), null, null, 0, 0);
        if (null != comment_cursor)
        {
            while (comment_cursor.hasNext())
            {
                TComment comment = ThriftUtil.dbObject2ThriftObject(comment_cursor.next(), TComment.class);
                comment_list.add(comment);
            }
            /* comment_num */
            for (TComment comment : comment_list)
            {
                /* recent fields */
                if (comment.getCtime() > recent_time)
                {
                    recent_time = comment.getCtime();
                    recent_user = comment.getUser_id();
                    recent_event = constConstants.RECENT_EVENT_COMMENT;
                }
            }
        }

        /* PRODUCT */
        double product_price = 0;
        List<TProduct> product_list = new ArrayList();

        if (null != diary.getProducts())
        {
            DBCursor product_cursor =
                Commons.mongo.cursor(Tables.Product, new BasicDBObject(TProduct._Fields._ID.getFieldName(), new BasicDBObject(QueryOperators.IN, diary.getProducts())), null, null, 0, 0);
            if (null != product_cursor)
            {
                while (product_cursor.hasNext())
                {
                    TProduct product = ThriftUtil.dbObject2ThriftObject(product_cursor.next(), TProduct.class);
                    product_list.add(product);
                }
                /* product_num */
                int product_num = product_list.size();
                for (TProduct product : product_list)
                {
                    /* recent fields */
                    if (product.getUtime() > recent_time)
                    {
                        recent_time = product.getUtime();
                        recent_user = diary.getOwner_id();
                        recent_event = constConstants.RECENT_EVENT_PRODUCT;
                    }
                    /* product_price */
                    product_price += product.getTotal_price();
                }
            }
        }

        /* DBUpdate */
        String stat_prefix = TDiary._Fields.STAT.getFieldName() + ".";
        update_db.put(TDiary._Fields.IMAGE_NUM.getFieldName(), image_num);
        update_db.put(stat_prefix + TDiaryStat._Fields.COMMENT_NUM.getFieldName(), comment_list.size());
        //		update_db.put(stat_prefix+TDiaryStat._Fields.PRODUCT_PRICE.getFieldName(), product_price);
        update_db.put(stat_prefix + TDiaryStat._Fields.RECENT_TIME.getFieldName(), recent_time);
        update_db.put(stat_prefix + TDiaryStat._Fields.RECENT_EVENT.getFieldName(), recent_event);
        update_db.put(stat_prefix + TDiaryStat._Fields.RECENT_USER.getFieldName(), recent_user);

        //		return Commons.mongo.findAndModify(Tables.Diary,
        //				new BasicDBObject("_id", diary_id), 
        //				null,null, false, new BasicDBObject("$set",update_db), true, StatWriter.upset);

        DBObject cond = new BasicDBObject("_id", diary_id);
        DBObject oper = new BasicDBObject("$set", update_db);
        mongo.update(Tables.Diary, cond, oper, false, false);

    }

    /**
     * 更新behavior行为统计，因为view行为不准备写入数据库，所以直接调用
     * @param scene_id
     * @param behavior_type
     * @param status
     * @return
     */
    @Override
    public void syncUpdate(String diary_id, int behavior_type, int status)
    {
        BasicDBObject inc = new BasicDBObject();
        String behavior_num_name = "";
        switch (behavior_type)
        {
            case constConstants.BEHAVIOR_TYPE_LIKE:
            {
                behavior_num_name = TDiaryStat._Fields.LIKE_NUM.getFieldName();
                break;
            }
        }

        if (StringUtil.isEmpty(behavior_num_name))
        {
            return;
        }

        inc.put(TDiary._Fields.STAT.getFieldName() + "." + behavior_num_name, status);
        BasicDBObject update = new BasicDBObject();
        update.put("$inc", inc);

        //		return Commons.mongo.findAndModify(Tables.Diary,
        //				new BasicDBObject(TDiary._Fields._ID.getFieldName(),diary_id),
        //				null,null,false,
        //				update, true, false);

        DBObject cond = new BasicDBObject(TDiary._Fields._ID.getFieldName(), diary_id);
        mongo.update(Tables.Diary, cond, update, false, false);
        logger.debug("cond:{},update:{}", cond, update);
    }

    @Override
    public void refreshCommentInfo(String diary_id, int recentTime, String userId, boolean setRecent, boolean setCommentNum)
    {
        List<Integer> diary_stat_tgt_list;
        diary_stat_tgt_list = new ArrayList<Integer>();
        diary_stat_tgt_list.add(constConstants.TARGET_TYPE_DIARY);
        refreshCommentNum(Tables.Diary, diary_id, recentTime, userId, setRecent, setCommentNum, true, STAT_PREFIX
            + TDiaryStat._Fields.COMMENT_NUM.getFieldName(), diary_stat_tgt_list);

        diary_stat_tgt_list = new ArrayList<Integer>();
        diary_stat_tgt_list.add(constConstants.TARGET_TYPE_DIARY);
        refreshCommentNum(Tables.Diary, diary_id, recentTime, userId, setRecent, setCommentNum, false, STAT_PREFIX
            + TDiaryStat._Fields.REF_COMMENT_NUM.getFieldName(), diary_stat_tgt_list);
    }

    @Override
    public void refreshProductInfo(String diary_id, int recentTime, String userId, boolean setRecent)
    {
        DBObject set = new BasicDBObject();

        // 查找该日记下的所有商品
        DBObject diary_db = mongo.findById(Tables.Diary, diary_id);
        if (null == diary_db)
            return;
        TDiary diary = ThriftUtil.dbObject2ThriftObject(diary_db, TDiary.class);
        List<String> productIds = diary.getProducts();

        List<String> product_id_list = new ArrayList();

        if (null != productIds)
        {
            DBObject cond = new BasicDBObject();
            cond.put(TProduct._Fields._ID.getFieldName(), new BasicDBObject("$in", productIds));
            cond.put(TProduct._Fields.STATUS.getFieldName(), constConstants.ENTITY_STATUS_NORM);

            DBCursor cursor = mongo.cursor(Tables.Product, cond, null, null, 0, 0);

            List<DBObject> product_db_list = cursor.toArray();

            double totalPrice = 0;

            for (DBObject product_db : product_db_list)
            {
                TProduct product = ThriftUtil.dbObject2ThriftObject(product_db, TProduct.class);

                product_id_list.add(product_db.get(TProduct._Fields._ID.getFieldName()).toString());
                totalPrice += product.getTotal_price();
            }
        }

        set.put(TDiary._Fields.PRODUCTS.getFieldName(), product_id_list);

        // TODO 只设置了总价

        DBObject oper = new BasicDBObject("$set", set);
        DBObject updateCond = new BasicDBObject("_id", diary_id);

        mongo.update(Tables.Diary, updateCond, oper, false, false);
        logger.debug("update for {}", set);
    }

    @Override
    public void refreshDiaryInfo(String tgt_id, int recentTime, String userId, boolean setRecent)
    {
        logger.debug("refreshDiaryInfo diary:{}", tgt_id);
        if (StringUtil.isEmpty(tgt_id))
        {
            logger.error("refreshDiaryInfo: tgt_id is Null or Empty!");
            return;
        }

        DBObject diary_db = mongo.findById(Tables.Diary, tgt_id);

        if (null == diary_db)
        {
            logger.error("error diary_db:{} with id:{}", diary_db, tgt_id);
            return;
        }

        TDiary diary = ThriftUtil.dbObject2ThriftObject(diary_db, TDiary.class);

        DBObject update_db = new BasicDBObject();

        /* IMAGE_NUM */
        int image_num = 0;
        if (null != diary.getImages())
            image_num = diary.getImagesSize();
        update_db.put(TDiary._Fields.IMAGE_NUM.getFieldName(), image_num);

        mongo.update(Tables.Diary, new BasicDBObject(TDiary._Fields._ID.getFieldName(), tgt_id), new BasicDBObject("$set", update_db), false, false);
        logger.debug("update for {}", update_db);
    }
}
